import { computed, onBeforeUnmount, ref, type Ref } from "vue";
import { ElNotification } from "element-plus";
import { difference } from "lodash";

export default (options: any) => {
  const { settingData } = options;

  let controler: any;

  const enum controlTypes {
    WHEEL = "方向盘",
    CONTROLLER = "手柄",
  }

  const controlerType = computed(() => {
    if (!controler) return "未知";
    return controler.id.includes("Wheel")
      ? controlTypes.WHEEL
      : controlTypes.CONTROLLER;
  });

  /**
   * @description: 初始手柄
   * @return {*}
   */
  const isConnect = ref("");
  function initGamepad() {
    const controlers = getConnectedGamepad();
    if (controlers.length === 0) {
      ElNotification({
        message: "未连接手柄",
        type: "warning",
      });
      isConnect.value = "未连接";
      return;
    }
    isConnect.value = "已连接";
    controler = findControler(controlers) || controlers[0];
    onGamepadOperation();
  }

  function findControler(controlers: any) {
    return controlers.find((item: any) => {
      item.id.includes("CONTROLLER");
    });
  }
  /**
   * @description: 与手柄断开连接
   * @return {*}
   */
  function disconnectGamepad() {
    controler = null;
    isConnect.value = "未连接";
  }

  /**
   * @description: 监听手柄连接/断开
   * @return {*}
   */
  function onGamepad() {
    window.addEventListener("gamepadconnected", initGamepad);
    window.addEventListener("gamepaddisconnected", disconnectGamepad);

    onBeforeUnmount(() => {
      disconnectGamepad();
      window.removeEventListener("gamepadconnected", initGamepad);
      window.removeEventListener("gamepaddisconnected", disconnectGamepad);
    });
  }

  onGamepad();

  /**
   * 获取已连接的游戏手柄数组
   * @returns {Gamepad[]} 已连接的游戏手柄数组
   */
  function getConnectedGamepad() {
    return navigator.getGamepads().filter((gamepad) => gamepad !== null);
  }

  getConnectedGamepad();

  /** 前进后退转向 */
  const direction = ref(0);
  /** 转向类型 */
  const directionType = ref("");
  const newAxes: Ref<number[]> = ref([]);
  const newBtns: Ref<GamepadButton[]> = ref([]);
  /**
   * @description: 实时监听手柄操作
   * @return {*}
   */
  function onGamepadOperation() {
    const gamepad = getConnectedGamepad().find(
      (item: any) => item.id === controler.id
    );
    if (!gamepad) return;
    const axes = gamepad.axes;
    newAxes.value = axes.slice();
    direction.value = setDirection(axes);
    const buttons = gamepad.buttons;
    newBtns.value = buttons.slice();
    handleButtons(buttons);
    requestAnimationFrame(onGamepadOperation);
  }

  /**
   * @description: 设置转向
   * @param {*} axes
   * @return {*}
   */
  /**
   * 判断左转前进右转前进
   */
  const isDirection = ref(false);

  function setDirection(axes: any) {
    let newDirection = 0;
    if (controlerType.value === controlTypes.CONTROLLER) {
      if (settingData.left !== "" && settingData.forward !== "") {
        const left = parseFloat(axes[settingData.left].toFixed(1));
        const forward = parseFloat(axes[settingData.forward].toFixed(1));
        if (forward === 0) {
          if (left === -1) {
            directionType.value = "R";
            newDirection = 2; // 向左
            isDirection.value = false;
          } else if (left === 1) {
            directionType.value = "R";
            newDirection = -2; // 向右
            isDirection.value = false;
          } else if (left === 0) {
            newDirection = 0;
          }
        } else if (forward === 1 && left === 0) {
          directionType.value = "L";
          newDirection = -2; // 向后
          isDirection.value = false;
        } else if (forward === -1) {
          if (left === -1) {
            directionType.value = "R";
            newDirection = 2;
            isDirection.value = true;
          } else if (left === 1) {
            directionType.value = "R";
            newDirection = -2;
            isDirection.value = true;
          } else if (left === 0) {
            directionType.value = "L";
            newDirection = 2; // 向前
            isDirection.value = false;
          }
        }
      }
    }
    return newDirection;
  }

  /**
   * 手柄按钮控制
   */
  let readyforClickButtons: any;
  const clickedButton = ref();

  function handleButtons(buttons: ReadonlyArray<GamepadButton>) {
    const pressedButtons = buttons
      .filter((button) => button.pressed)
      .map((i) => buttons.findIndex((j) => j === i));
    const diff = difference(readyforClickButtons, pressedButtons);
    readyforClickButtons = pressedButtons;
    diff.forEach((i) => {
      clickedButton.value = i;
    });
  }
  return {
    initGamepad,
    direction,
    disconnectGamepad,
    directionType,
    isConnect,
    isDirection,
    clickedButton,
    newAxes,
    newBtns,
  };
};
